#include "OpFilter.h"
#include "Exp.h"
#include "proto/internal.pb.h"

using namespace internal;

template<class T>
inline int rewrite(void *destination, void* source, bool* conditions, int size) {
	T* dest = (T*) destination;
	T* src = (T*) source;
	int next = 0;
	for (int i = 0; i < size; i++)
		if (conditions[i])
			dest[next++] = src[i];
	return next;
}

OpFilter::OpFilter(const FilterOperation& operation) {
	// printf("tworze OpFilter\n") ;
	source = createOp(operation.source());
	input = source->getOutput();

	expression = createExp(operation.expression(), input);

	Output_elem elem = expression->getOutputElem();
	assert(elem.type == BOOL);
	conditions = (bool*) elem.column;

	// alokacja nowych wskaznikow
	output = input;
	for (size_t i = 0; i < output.size(); i++) {
		switch (output[i].type) {
		case INT:
			output[i].column = malloc(sizeof (int32_t) * TABLESIZE);
			break;
		case DOUBLE:
			output[i].column = malloc(sizeof (double) *TABLESIZE);
			break;
		case BOOL:
			output[i].column = malloc(sizeof (bool) * TABLESIZE);
			break;
		}
	}
}

int OpFilter::doit() {
	int size = source->doit();
	if (size == -1) return -1;
	else {
		expression->doit(size);
		int ret = 0;
		for (size_t i = 0; i < output.size(); i++) {
			switch (input[i].type) {
			case INT:
				ret = rewrite<int32_t > (output[i].column, input[i].column, conditions, size);
				break;
			case DOUBLE:
				ret = rewrite<double>(output[i].column, input[i].column, conditions, size);
				break;
			case BOOL:
				ret = rewrite<bool>(output[i].column, input[i].column, conditions, size);
				break;
			}
		}
		return ret;
	}
}
